/*
Copyright 2010  Murali Devi (profdevi@gmail.com)

This file is part of ComineGL Project.

ComineGL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ComineGL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ComineGL.  If not, see <http://www.gnu.org/licenses/>.

This code uses the irrlicht and irrklang libraries.  Please read
the libraries copyrights at 

	irrlicht library:  http://irrlicht.sourceforge.net
	irrklang library:  http://www.ambiera.com/irrklang

*/



//v1.4 copyright Comine.com 20101211S22
#include "MStdLib.h"
#include "MIrrlicht.h"
#include "MCGLEventInput.h"


//******************************************************
//**  Module Elements
//******************************************************
static const int GMouseResolution=50;			// 50 ms resolution
static const int GMouseClickResolution=50;		// 50 ms resolution
static const int GKeyboardResolution=50;		// 50 ms resolution


//******************************************************
//**  MCGLEventInput class
//******************************************************
void MCGLEventInput::ClearObject(void)
	{
	mIrrlichtDevice=NULL;

	int i;
	for(i=0;i<KEY_KEY_CODES_COUNT;++i)
		{
		mKeyPressTime[i]=~0;
		mKeyIsPressedCount[i]=0;
		}

	mClockTime=0;

	mMouseTime=0;
	mMousePosX=0;
	mMousePosY=0;
	mMouseDeltaX=0;
	mMouseDeltaY=0;

	mMouseRightClickTime=0;
	mMouseLeftClickTime=0;

	mRawKeyboardHandler=NULL;
	mRawKeyboardHandlerExtra=NULL;
	}


////////////////////////////////////////////////
MCGLEventInput::MCGLEventInput(void)
	{  ClearObject();  }


////////////////////////////////////////////////
MCGLEventInput::~MCGLEventInput(void)
	{  Destroy();  }


////////////////////////////////////////////////
bool MCGLEventInput::Create(IrrlichtDevice *device)
	{
	Destroy();
	if(device==NULL)
		{
		Destroy();
		return false;
		}

	// Grab on to device
	mIrrlichtDevice=device;
	mIrrlichtDevice->grab();

	return true;
	}


////////////////////////////////////////////////
bool MCGLEventInput::Destroy(void)
	{
	if(mIrrlichtDevice!=NULL)
		{
		mIrrlichtDevice->drop();
		mIrrlichtDevice=NULL;
		}

	ClearObject();
	return true;
	}


///////////////////////////////////////////////
bool MCGLEventInput::OnEvent(const SEvent& evt)
	{
	if(evt.EventType==EET_MOUSE_INPUT_EVENT)
		{
		// Save Mouse Time
		mMouseTime=mClockTime;

		int x=evt.MouseInput.X;
		int y=evt.MouseInput.Y;
		
		// Update Mouse delta
		mMouseDeltaX = x-mMousePosX;
		mMouseDeltaY = y-mMousePosY;

		// Update Position
		mMousePosX = x;
		mMousePosY = y;

		// 
		if( (mClockTime<mMouseRightClickTime || mClockTime>mMouseRightClickTime+GMouseClickResolution)
				&& evt.MouseInput.isRightPressed()==true )
			{
			mMouseRightClickTime=mClockTime;
			}

		if( (mClockTime<mMouseLeftClickTime || mClockTime>mMouseLeftClickTime+GMouseClickResolution)
				&& evt.MouseInput.isLeftPressed()==true )
			{
			mMouseLeftClickTime=mClockTime;
			}

		return false;
		}
	else if(evt.EventType==EET_KEY_INPUT_EVENT)
		{
		// Get key code
		const int keycode=evt.KeyInput.Key;

		if(mRawKeyboardHandler!=NULL)
			{
			if(mRawKeyboardHandler(keycode,mRawKeyboardHandlerExtra)==false)
				{
				// User requested no regular processing of key
				return false;
				}
			}

		// Skip key release
		if(evt.KeyInput.PressedDown==false)
			{
			return false;
			}

		// Skip 2nd key press within time period
		if(mClockTime>=mKeyPressTime[keycode] 
				&& mClockTime<=mKeyPressTime[keycode]+GKeyboardResolution)
			{
			return false;
			}

		mKeyPressTime[keycode] = mClockTime;
		mKeyIsPressedCount[keycode] = 0;
		return false;
		}
	
	return false;
	}


///////////////////////////////////////////////
bool MCGLEventInput::IsKeyPressed(int keycode)
	{
	MStdAssert(keycode>=0 && keycode<KEY_KEY_CODES_COUNT);
	if(mClockTime>=mKeyPressTime[keycode] 
			&& mClockTime<=mKeyPressTime[keycode]+GKeyboardResolution
			&& mKeyIsPressedCount[keycode]==0)
		{
		mKeyIsPressedCount[keycode] = mKeyIsPressedCount[keycode] + 1;
		return true;
		}

	return false;
	}


///////////////////////////////////////////////
bool MCGLEventInput::GetMousePosition(int &x,int &y)
	{
	x=mMousePosX;
	y=mMousePosY;
	return true;
	}


///////////////////////////////////////////////
bool MCGLEventInput::GetMouseDelta(int &dx,int &dy)
	{
	dx=mMouseDeltaX;	
	dy=mMouseDeltaY;
	return true;
	}


////////////////////////////////////////////////
bool MCGLEventInput::UpdateTime(void)
	{
	mClockTime=mIrrlichtDevice->getTimer()->getRealTime();

	if(mClockTime<mMouseTime)
		{
		mMouseTime=0;
		}

	// Update Delta Mouse Pos 
	if(mClockTime-mMouseTime>GMouseResolution)
		{
		mMouseDeltaX=0;
		mMouseDeltaY=0;
		}

	return true;
	}


/////////////////////////////////////////////////
bool MCGLEventInput::IsMouseRightPressed(void)
	{

	if(mClockTime>=mMouseRightClickTime	&& mClockTime<=mMouseRightClickTime+GMouseClickResolution)
		{
		// Called only once in time resolution
		mMouseRightClickTime=0;
		return true;
		}

	return false;
	}


/////////////////////////////////////////////////
bool MCGLEventInput::IsMouseLeftPressed(void)
	{

	if(mClockTime>=mMouseLeftClickTime	&& mClockTime<=mMouseLeftClickTime+GMouseClickResolution)
		{
		// Called only once in time resolution
		mMouseLeftClickTime=0;
		return true;
		}

	return false;
	}


////////////////////////////////////////////////
bool MCGLEventInput::SetKeyboardHandler(bool KeyboardHandler(int keycode,void *extra),void *extra)
	{
	mRawKeyboardHandler=KeyboardHandler;
	mRawKeyboardHandlerExtra=extra;
	return true;
	}

